namespace ScrumSprintMonitor.Implementation
{
	#region #using Directives

	using System;
	using System.Collections.Generic;

	using Infrastructure;

	using Ninject.Core;
	using Ninject.Core.Parameters;

	#endregion

	public class ConnectionProvider : IConnectionProvider,
	                                  IDisposable
	{
		private readonly IKernel kernel;
		private IConnection connection;
		private Uri serverUri;

		public ConnectionProvider(IKernel kernel)
		{
			this.kernel = kernel;
		}

		#region Implementation of IConnectionProvider

		public IConnection ProvideConnectionTo(Uri requestedServerUri, string userName, string password, bool reuseExisting)
		{
			if (reuseExisting && requestedServerUri.Equals(this.serverUri))
			{
				return this.connection;
			}

			if (userName == null)
			{
				userName = string.Empty;
			}
			if (password == null)
			{
				password = string.Empty;
			}

			var requestedConnection = this.kernel.Get<IConnection>(With.Parameters.ConstructorArguments(new Dictionary<string, object>
			                                                                                            	{
			                                                                                            		{
			                                                                                            			"serverUri",
			                                                                                            			requestedServerUri
			                                                                                            			},
			                                                                                            		{"userName", userName},
			                                                                                            		{"password", password}
			                                                                                            	}));

			DisposeConnections();

			this.serverUri = requestedServerUri;
			this.connection = requestedConnection;

			return this.connection;
		}

		private void DisposeConnections()
		{
			var disposable = this.connection as IDisposable;
			if (disposable != null)
			{
				disposable.Dispose();
			}

			this.serverUri = null;
			this.connection = null;
		}

		#endregion

		#region Implementation of IDisposable

		public void Dispose()
		{
			DisposeConnections();
		}

		#endregion
	}
}